package be.kuleuven.cs.mop.gui.dialogs;


import java.awt.Dimension;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;

import be.kuleuven.cs.mop.app.controllers.Controllers;
import be.kuleuven.cs.mop.domain.exceptions.InvalidCurrentUserException;
import be.kuleuven.cs.mop.domain.exceptions.TaskManagerException;
import be.kuleuven.cs.mop.domain.model.Reservation;
import be.kuleuven.cs.mop.domain.model.Resource;
import be.kuleuven.cs.mop.domain.model.Task;
import be.kuleuven.cs.mop.gui.components.ActionButton;
import be.kuleuven.cs.mop.gui.components.ComboSelector;
import be.kuleuven.cs.mop.gui.components.DateInput;
import be.kuleuven.cs.mop.gui.components.DurationInput;
import be.kuleuven.cs.mop.gui.components.SelectionList;
import be.kuleuven.cs.mop.gui.components.Wrapper;
import be.kuleuven.cs.mop.gui.util.Representation;
import be.kuleuven.cs.mop.gui.util.SwingUtils;



/**
 * {@link ActionDialog} for the "Make Resource Reservation for Task" use case
 */
public class MakeResourceReservationForTaskDialog
		extends DynamicActionDialog<Resource> {
	private static final long serialVersionUID = 1L;
	
	private DateInput						date			= new DateInput();
	private DurationInput					duration		= new DurationInput();
	private Wrapper<SelectionList<Entry>>	reservations;
	private ComboSelector<Resource>			resources;
	private ComboSelector<Task>				tasks;
	
	
	public MakeResourceReservationForTaskDialog(final Frame parent,
			final Controllers controllers) {
		super(parent, "Make Resource Reservation for Task", controllers);
		final GridBagConstraints gbc = SwingUtils.getGBC();
		
		try {
			final List<Task> tasks =
				getControllers().getControllerTasks().getUserTasksUnfinished();
			this.tasks	= new ComboSelector<Task>(
					tasks.toArray(new Task[tasks.size()]));
			
			final List<Resource> resources =
				getControllers().getControllerResources().getResources();
			this.resources = new ComboSelector<Resource>(
					resources.toArray(new Resource[resources.size()]));
		} catch (final Exception e) {
			log(e);
			dispose();
			return;
		}
		
		reservations = new Wrapper<SelectionList<Entry>>(new Dimension(500, 350));
		
		try {
			update(getSelection());
		} catch (final Exception e) {
			//	ignored
		}
		
		gbc.gridx	= 0;
		gbc.gridy	= 0;
		gbc.gridwidth	= 2;
		add(tasks, gbc);
		
		resources.addActionListener(new UpdateListener());
		gbc.gridy	= 1;
		add(resources, gbc);
		
		gbc.gridy	= 2;
		gbc.gridwidth	= 1;
		gbc.gridheight	= 3;
		add(reservations, gbc);
		
		gbc.gridx	= 1;
		gbc.gridheight	= 1;
		add(date, gbc);
		
		gbc.gridy	= 3;
		add(duration, gbc);
		
		gbc.gridy	= 4;
		add(new ActionButton("Confirm", new Dimension(150, 32), this), gbc);
		
		display();
	}
	
	
	
	@Override
	protected Resource getSelection() {
		return resources.getSelection();
	}
	
	@Override
	protected void handle(final ActionEvent event)
			throws InvalidCurrentUserException, TaskManagerException {
		final Resource	resource	= resources.getSelection();
		if (resource == null) {
			log("Please select a Resource", Level.WARNING);
			return;
		}
		
		final Task task	= tasks.getSelection();
		if (task == null) {
			log("Please select a Task", Level.WARNING);
			return;
		}
		
		getControllers().getControllerResources().makeResourceReservation(
				task, resource, date.read(), duration.read());
		log("Reserved '%s' for '%s'", resource, task);
		dispose();
	}
	
	@Override
	protected void update(final Resource selection) {
		reservations.set(new SelectionList<Entry>(
				Entry.wrap(selection.getReservations()), false));
	}
	
	
	
	
	
	
	
	
	
	
	private static class Entry extends Representation<Reservation> {
		
		private Entry(final Reservation reservation) {
			super(reservation);
		}
		
		
		
		@Override
		public String toString() {
			return String.format("%s - %s",
					get().getDate().getTime(),
					get().getEnd().getTime());
		}
		
		public static final List<Entry> wrap(
				final Set<? extends Reservation> reservations) {
			final List<Entry> list = new ArrayList<Entry>();
			for (final Reservation reservation : reservations)
				list.add(new Entry(reservation));
			return list;
		}
		
	}
	
}